package com.ailk.evaluation.evaluation;

import java.util.*;

public class EvaluationTemplate {

	private String id;
	private String name;
	private String remark;

	private Vector<EvaluationNode> roots;
	private Vector<EvaluationNode> leaves;
	private HashMap<String, EvaluationNode> nodes;
	
	private EvaluationNode addNode(EvaluationEntry entry){
		if((entry != null) && (!nodes.containsKey(entry.getId()))){
			EvaluationNode node = new EvaluationNode(entry, null, null, null, 0, 0);
			nodes.put(entry.getId(), node);
			return node;
		}
		
		return null;
	}
	
	private EvaluationNode removeNode(EvaluationEntry entry){
		if((entry != null) && (nodes.containsKey(entry.getId()))){
			EvaluationNode node = nodes.get(entry.getId());
			nodes.remove(entry.getId());
			return node;
		}
		
		return null;
	}
	
	private EvaluationNode getNode(EvaluationEntry entry){
		if((entry != null) && (nodes.containsKey(entry.getId()))){
			return nodes.get(entry.getId());
		}
		
		return null;
	}

	private boolean addLeaf(EvaluationNode node){
		leaves.add(node);
		node.setLeafCount(0);
		EvaluationNode parentNode = node.getParentNode();
		while(parentNode != null){
			parentNode.setLeafCount(parentNode.getLeafCount()+1);
			parentNode = parentNode.getParentNode();
		}
		
		return true;
	}
	
	private boolean removeLeaf(EvaluationNode node){
		leaves.remove(node);
		EvaluationNode parentNode = node.getParentNode();
		while(parentNode != null){
			parentNode.setLeafCount(parentNode.getLeafCount()-1);
			parentNode = parentNode.getParentNode();
		}
		
		return true;
	}
	
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}
	
	public EvaluationTemplate(){
		roots = new Vector<EvaluationNode>();
		leaves = new Vector<EvaluationNode>();
		nodes = new HashMap<String, EvaluationNode>();
	}
	
	public boolean addRoot(EvaluationEntry entry){
		EvaluationNode node = addNode(entry);
		if(node != null){
			node.setBrotherNodes(roots);
			roots.add(node);
			addLeaf(node);
			return true;
		}
		
		return false;
	}
	
	public boolean addChild(EvaluationEntry parentEntry, EvaluationEntry entry){
		if(parentEntry == null){
			return addRoot(entry);
		}else{
			EvaluationNode parentNode = getNode(parentEntry);
			EvaluationNode node = addNode(entry);
			
			if((parentNode != null) && (node != null)){
				if(parentNode.getChildrenNodes() == null){
					Vector<EvaluationNode> children = new Vector<EvaluationNode>();
					children.add(node);
					parentNode.setChildrenNodes(children);
					node.setParentNode(parentNode);
					node.setBrotherNodes(children);
					node.setLevel(node.getParentNode().getLevel()+1);
					removeLeaf(parentNode);
					addLeaf(node);
				}else{
					Vector<EvaluationNode> children = parentNode.getChildrenNodes();
					children.add(node);
					node.setParentNode(parentNode);
					node.setBrotherNodes(children);
					node.setLevel(node.getParentNode().getLevel()+1);
					addLeaf(node);
				}
				
				return true;
			}
			
			removeNode(entry);
			return false;
		}

	}
	
	public EvaluationEntry getEntryById(String id){
		if(nodes.containsKey(id)){
			return nodes.get(id).getEntry();
		}
		
		return null;
	}
	
	public EvaluationEntry getParentEntry(EvaluationEntry entry){
		EvaluationNode node = getNode(entry);

		if(node != null){
			EvaluationNode parentNode = node.getParentNode();
			if(parentNode != null){
				return parentNode.getEntry();
			}
		}
		
		return null;
	}
	
	public EvaluationEntry[] getChildrenEntries(EvaluationEntry entry){
		EvaluationNode node = getNode(entry);

		if(node != null){
			Vector<EvaluationNode> children = node.getChildrenNodes();
			if(children != null){
				EvaluationEntry[] childrenEntries = new EvaluationEntry[children.size()];
				for(int i = 0; i < children.size(); i++){
					childrenEntries[i] = children.get(i).getEntry();
				}
				return childrenEntries;
			}	
		}
		
		return null;
	}
	
	public EvaluationEntry[] getBrotherEntries(EvaluationEntry entry){
		EvaluationNode node = getNode(entry);

		if(node != null){
			Vector<EvaluationNode> brother = node.getBrotherNodes();
			EvaluationEntry[] brotherEntries = new EvaluationEntry[brother.size()];
			for(int i = 0; i < brother.size(); i++){
				brotherEntries[i] = brother.get(i).getEntry();
			}
			return brotherEntries;
		}
		
		return null;
	}
	
	public EvaluationEntry getPreviousEntry(EvaluationEntry entry){
		EvaluationNode node = getNode(entry);
		
		if(node != null){
			Vector<EvaluationNode> brother = node.getBrotherNodes();
			int index = brother.indexOf(node);
			if(--index >= 0){
				return brother.get(index).getEntry();
			}
		}
		
		return null;
	}
	
	public EvaluationEntry getNextEntry(EvaluationEntry entry){
		EvaluationNode node = getNode(entry);
		
		if(node != null){
			Vector<EvaluationNode> brother = node.getBrotherNodes();
			int index = brother.indexOf(node);
			if(++index < brother.size()){
				return brother.get(index).getEntry();
			}
		}
		
		return null;
	}
	
	public EvaluationEntry[] getRootEntries(){
		if((roots != null) && (roots.size() > 0)){
			EvaluationEntry[] rootEntries = new EvaluationEntry[roots.size()];
			for(int i = 0; i < roots.size(); i++){
				rootEntries[i] = roots.get(i).getEntry();
			}
			return rootEntries;
		}
		
		return null;
	}
	
	public EvaluationEntry[] getLeafEntries(){
		if((leaves != null) && (leaves.size() > 0)){
			EvaluationEntry[] LeafEntries = new EvaluationEntry[leaves.size()];
			for(int i = 0; i < leaves.size(); i++){
				LeafEntries[i] = leaves.get(i).getEntry();
			}
			return LeafEntries;
		}
		
		return null;
	}
	
	public int getChildrenCount(EvaluationEntry entry){
		EvaluationNode node = getNode(entry);

		if(node != null){
			Vector<EvaluationNode> children = node.getChildrenNodes();
			
			if(children != null){
				return children.size();
			}
		}
		
		return -1;
	}
	
	public int getBrotherCount(EvaluationEntry entry){
		EvaluationNode node = getNode(entry);

		if(node != null){
			return node.getBrotherNodes().size();
		}
		
		return -1;
	}
	
	public int getLeafCount(EvaluationEntry entry){
		EvaluationNode node = getNode(entry);

		if(node != null){
			return node.getLeafCount();
		}
		
		return -1;
	}
	
	public int getEntryLevel(EvaluationEntry entry){
		EvaluationNode node = getNode(entry);

		if(node != null){
			return node.getLevel();
		}
		
		return -1;
	}
	
}
